package com.feizhaiyou.demo.aop;


import com.feizhaiyou.demo.anno.DataSource;
import com.feizhaiyou.demo.holder.DynamicDataSourceContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 多数据源处理
 *
 * @author Jason
 */
@Aspect
@Order(1)
@Component
public class DataSourceAspect {
    // 切点
    @Pointcut("@annotation(com.feizhaiyou.demo.anno.DataSource)"
            + "|| @within(com.feizhaiyou.demo.anno.DataSource)")
    public void dsPointCut() {

    }

    @Around("dsPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        // 获取该切点的DataSource注解
        DataSource dataSource = getDataSource(point);

        if (dataSource != null) {
            // 设置数据源key 通过该key获取DynamicDataSource中指定的动态数据源
            DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
        }

        try {
            return point.proceed();
        } finally {
            // 销毁数据源 在执行方法之后 清空数据源key 释放该数据源
            DynamicDataSourceContextHolder.clearDataSourceType();
        }
    }

    /**
     * 获取切点上的DataSource注解{@link DataSource}
     * @param point 切点
     * @return {@link DataSource}
     */
    private DataSource getDataSource(ProceedingJoinPoint point) {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Class<? extends Object> targetClass = point.getTarget().getClass();
        DataSource targetDataSource = targetClass.getAnnotation(DataSource.class);
        if (targetDataSource != null) {
            return targetDataSource;
        } else {
            Method method = signature.getMethod();
            DataSource dataSource = method.getAnnotation(DataSource.class);
            return dataSource;
        }
    }
}
